﻿using System;

namespace Ndns.Packet.Text
{
    internal static class Punycode
    {
        public const int TMIN = 1;
        public const int TMAX = 26;
        public const int BASE = 36;
        public const int INITIAL_N = 128;
        public const int INITIAL_BIAS = 72;
        public const int DAMP = 700;
        public const int SKEW = 38;
        public const char DELIMITER = '-';


        public static int Adapt(int delta, int numpoints, bool first)
        {
            if (first)
            {
                delta = delta / DAMP;
            }
            else
            {
                delta = delta / 2;
            }
            delta = unchecked(delta + (delta / numpoints));
            int k = 0;
            while (delta > unchecked((BASE - TMIN) * TMAX) / 2)
            {
                delta = delta / (BASE - TMIN);
                k = unchecked(k + BASE);
            }
            return unchecked(k + ((BASE - TMIN + 1) * delta) / (delta + SKEW));
        }
        public static bool IsBasic(char c)
        {
            return c < 0x80;
        }
        public static int DigitToCodepoint(int d)
        {
            if (d < 26)
            {
                // 0..25 : 'a'..'z'
                return unchecked(d + 'a');
            }
            else if (d < 36)
            {
                // 26..35 : '0'..'9';
                return unchecked(d - 26 + '0');
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(d));
            }
        }
        public static int CodepointToDigit(int c)
        {
            if (c - '0' < 10)
            {
                // '0'..'9' : 26..35
                return unchecked(c - '0' + 26);
            }
            else if (c - 'a' < 26)
            {
                // 'a'..'z' : 0..25
                return c - 'a';
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(c));
            }
        }
    }
}
